#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <strings.h>
#include <string>
#include <string.h>
#include <cstdio>
#include <unistd.h>
#include <pthread.h>

using namespace std;

struct Thread
{
    int sockfd;
    struct sockaddr_in server;
};

void usage(char *argv[])
{
    cout << "please input like: " << argv[0] << " ip"
         << " port[1024+]" << endl;
}

void *receiver(void *args)
{
    Thread *thread = static_cast<Thread *>(args);
    char recvbuffer[1024] = {0};

    while (true)
    {
        // 接收
        memset(recvbuffer, 0, sizeof(recvbuffer));

        struct sockaddr_in temp;
        socklen_t len2 = sizeof(temp); 
        ssize_t s = recvfrom(thread->sockfd, recvbuffer, sizeof(recvbuffer) - 1, 0, (sockaddr *)&temp, &len2);
        if (s > 0)
        {
            recvbuffer[s] = 0; // 这里一定要加0
            cerr << recvbuffer << endl;
        }
    }
}

void *sender(void *args)
{
    Thread *thread = static_cast<Thread *>(args);
    string message;

    while (true)
    {
        // 发送
        cout << "client send: ";
        getline(cin, message);
        sendto(thread->sockfd, message.c_str(), message.size(), 0, (const sockaddr *)&thread->server, sizeof(thread->server));
        // usleep(100000);
    }
}

int main(int argc, char *argv[])
{

    if (argc != 3)
    {
        // 命令行参数不正确
        usage(argv);
        return 1;
    }

    Thread thread;

    // 创建socket
    thread.sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (thread.sockfd < 0)
    {
        cout << "socket failed" << endl;
        return 2;
    }
    // 服务器的IP地址和端口号
    uint16_t port = atoi(argv[2]);
    string ip = argv[1];

    bzero(&thread.server, sizeof(thread.server));
    thread.server.sin_family = AF_INET;
    thread.server.sin_port = htons(port);
    thread.server.sin_addr.s_addr = inet_addr(ip.c_str());
    // 客户端也需要绑定，但是我们可以不写出来，只不过系统帮我们做了

    pthread_t Recv, Send;

    pthread_create(&Recv, nullptr, receiver, &thread);
    pthread_create(&Send, nullptr, sender, &thread);

    pthread_join(Recv, nullptr);
    pthread_join(Send, nullptr);

    close(thread.sockfd);
    return 0;
}